﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using Icoders.MarketTracker.Core.MasterData;
using Icoders.MarketTracker.Core.Repository.MasterDataRepositories;
using Icoders.MarketTracker.Core.Validation;
using Icoders.MarketTracker.Data.EF;
using Icoders.MarketTracker.Data.Utils;
using Icoders.MarketTracker.Data.Utils.Caching;

namespace Icoders.MarketTracker.Data.Repository.MasterDataRepositories
{
    public class NewsRepository : RepositoryBase, INewsRepository
    {
        private AppDataContext _ctx;
        private ICacheProvider _cacheProvider;

        public NewsRepository(AppDataContext ctx, ICacheProvider cacheProvider)
        {
            _ctx = ctx;
            _cacheProvider = cacheProvider;
        }

        public int Save(News entity)
        {
            ValidationResultInfo vri = Validate(entity);
            if (!vri.IsValid)
            {
                throw new DomainValidationException(vri, "News Details provided not Valid");
            }
            DateTime date = TimeUtil.GetDateTime();
            TblNews tbl = _ctx.TblNews.FirstOrDefault(s => s.Id == entity.Id);
            if (tbl == null)
            {
                tbl = new TblNews();
                tbl.CreatedOn = date;
                tbl.StatusId = (int)MasterEntityStatus.New;
                _ctx.TblNews.AddObject(tbl);
            }
            tbl.UpdatedOn = date;
            tbl.Narration = entity.Narration;
            tbl.Subject = entity.Subject;
            _ctx.SaveChanges();
            _cacheProvider.Put(_cacheListKey, _ctx.TblNews.Where(x => x.StatusId != 3).Select(s => s.Id).ToList());
            _cacheProvider.Remove(string.Format(_cacheKey, tbl.Id));
            return tbl.Id;
        }

        public News GetById(int id)
        {
            News entity = (News)_cacheProvider.Get(string.Format(_cacheKey, id));
            if (entity == null)
            {
                var tbl = _ctx.TblNews.FirstOrDefault(s => s.Id == id);
                if (tbl != null)
                {
                    entity = Map(tbl);
                    _cacheProvider.Put(string.Format(_cacheKey, entity.Id), entity);
                }

            }
            return entity;
        }

        public List<News> GetAll()
        {
            IList<News> entities = null;
            IList<int> ids = (IList<int>)_cacheProvider.Get(_cacheListKey);
            if (ids != null)
            {
                entities = new List<News>(ids.Count);
                foreach (int id in ids)
                {
                    News entity = GetById(id);
                    if (entity != null)
                        entities.Add(entity);
                }
            }
            else
            {
                entities = _ctx.TblNews.Where(x => x.StatusId != 3).ToList().Select(s => Map(s)).ToList();
                if (entities != null && entities.Count > 0)
                {
                    ids = entities.Select(s => s.Id).ToList(); 
                    _cacheProvider.Put(_cacheListKey, ids);
                    foreach (News p in entities)
                    {
                        _cacheProvider.Put(string.Format(_cacheKey, p.Id), p);
                    }

                }
            }
            return entities.ToList();
        }

        public void Delete(int id)
        {
            var tbl = _ctx.TblNews.FirstOrDefault(s => s.Id == id);
            if (tbl != null)
            {
                tbl.StatusId = (int)MasterEntityStatus.Deleted;
                _ctx.SaveChanges();
                _cacheProvider.Put(_cacheListKey, _ctx.TblNews.Where(x => x.StatusId != 3).Select(s => s.Id).ToList());
                _cacheProvider.Remove(string.Format(_cacheKey, tbl.Id));
            }
        }

        private News Map(TblNews tblNews)
        {
            return new News()
            {
                Id = tblNews.Id,
                Narration = tblNews.Narration,
                Subject = tblNews.Subject,
                UpdatedOn = tblNews.UpdatedOn,
                CreatedOn = tblNews.CreatedOn,
                Status = (MasterEntityStatus)tblNews.StatusId

            };
        }

        public ValidationResultInfo Validate(News objToValidate)
        {
            ValidationResultInfo vri = objToValidate.BasicValidation();
            bool hasDuplicateName = GetAll().Where(v => v.Id != objToValidate.Id)
                .Any(p => p.Subject == objToValidate.Subject);
            if (hasDuplicateName)
                vri.Results.Add(new ValidationResult("Duplicate Subject Found"));
            return vri;
        }
        protected override string _cacheKey
        {
            get { return "News-{0}"; }
        }

        protected override string _cacheListKey
        {
            get { return "NewsList"; }
        }
    }
}
